package cn.net.isir.common;

import org.apache.log4j.Logger;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * @author liuxubo
 * @filename CustomHttpServletRequest.java
 * @package com.jy.common
 * @email lxb@isir.net.cn
 * @date 2018/04/16
 * @comment
 * @since 1.7
 */
public class CustomHttpServletRequest extends HttpServletRequestWrapper {
    private static Logger logger = Logger.getLogger(CustomHttpServletRequest.class);
    private HttpServletRequest servletRequest;
    private byte data[];

    public CustomHttpServletRequest(ServletRequest request) {
        super((HttpServletRequest) request);
        this.servletRequest = (HttpServletRequest) request;
    }

    public byte[] getCopy() throws IOException {
        byte[] buf = new byte[1024];
        byte[] tmp;
        int len;
        data = new byte[0];
        try {
            while ((len = servletRequest.getInputStream().read(buf)) != -1) {
                tmp = new byte[data.length];
                //将data中保存的数据暂存到tmp
                System.arraycopy(data, 0, tmp, 0, data.length);
                //扩展数组
                data = new byte[data.length + len];
                //将tmp中的数据取回到data
                System.arraycopy(tmp, 0, data, 0, tmp.length);
                //将新读取的数据放入data
                System.arraycopy(buf, 0, data, tmp.length, len);
            }
            logger.info(data.length);
            if (servletRequest.getCharacterEncoding() != null) {
                logger.info(new String(data, servletRequest.getCharacterEncoding()));
            } else {
                logger.info(new String(data));
            }
        } catch (IOException e) {
//            e.printStackTrace();
            logger.error(e);
        }

        return data;
    }


    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(data);
        return new ServletInputStream() {
            /**
             * Returns true when all the data from the stream has been read else
             * it returns false.
             *
             * @return <code>true</code> when all data for this particular request
             * has been read, otherwise returns <code>false</code>.
             * @since Servlet 3.1
             */
            @Override
            public boolean isFinished() {
                return false;
            }

            /**
             * Returns true if data can be read without blocking else returns
             * false.
             *
             * @return <code>true</code> if data can be obtained without blocking,
             * otherwise returns <code>false</code>.
             * @since Servlet 3.1
             */
            @Override
            public boolean isReady() {
                return false;
            }

            /**
             * Instructs the <code>ServletInputStream</code> to invoke the provided
             * {@link ReadListener} when it is possible to read
             *
             * @param readListener the {@link ReadListener} that should be notified
             *                     when it's possible to read.
             * @throws IllegalStateException if one of the following conditions is true
             *                               <ul>
             *                               <li>the associated request is neither upgraded nor the async started
             *                               <li>setReadListener is called more than once within the scope of the same request.
             *                               </ul>
             * @throws NullPointerException  if readListener is null
             * @since Servlet 3.1
             */
            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() {
                return bais.read();
            }
        };
    }
}
